package com.ruoyi.proposal.controller;

import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 提案图片上传控制器
 */
@RestController
@RequestMapping("/proposal")
public class ProposalImageController extends BaseController {

    // 从配置文件中读取上传目录
    @Value("${proposal.upload.dir}")
    private String uploadDir;

    // 从配置文件中读取允许的文件大小（MB）
    @Value("${proposal.upload.maxSize}")
    private Long maxFileSize;

    // 从配置文件中读取允许的文件类型
    @Value("${proposal.upload.allowedTypes}")
    private String[] allowedTypes;

    // 使用原子整数确保线程安全的计数器
    private final AtomicInteger counter = new AtomicInteger(1);

    /**
     * 初始化方法，确保计数器每天重置
     */
    @PostConstruct
    public void init() {
        // 初始化计数器为1
        counter.set(1);
    }

    /**
     * 上传图片
     * @param image 图片文件
     * @param proposerId 提案人ID
     * @return 上传结果
     */
    @PostMapping("/upload")
    public AjaxResult uploadImage(@RequestParam("image") MultipartFile image,
                                  @RequestParam(value = "proposerId", required = false) Integer proposerId) {
        if (image.isEmpty()) {
            return AjaxResult.error("上传文件不能为空");
        }

        try {
            // 检查文件类型
            String contentType = image.getContentType();
            boolean typeAllowed = false;
            for (String type : allowedTypes) {
                if (type.equals(contentType)) {
                    typeAllowed = true;
                    break;
                }
            }

            if (!typeAllowed) {
                StringBuilder allowedTypesStr = new StringBuilder();
                for (String type : allowedTypes) {
                    if (allowedTypesStr.length() > 0) {
                        allowedTypesStr.append(", ");
                    }
                    allowedTypesStr.append(type);
                }
                return AjaxResult.error("只支持以下格式的图片: " + allowedTypesStr.toString());
            }

            // 检查文件大小
            if (image.getSize() > maxFileSize * 1024 * 1024) {
                return AjaxResult.error("图片大小不能超过" + maxFileSize + "MB");
            }

            // 创建上传目录（按日期分目录）
            String datePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
            String finalUploadDir = uploadDir + File.separator + datePath;
            File uploadDirFile = new File(finalUploadDir);
            if (!uploadDirFile.exists()) {
                uploadDirFile.mkdirs();
            }

            // 生成按"日期_工号_序号"命名的文件名
            String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
            int count = counter.getAndIncrement();
            String fileExtension = ".jpg"; // 默认jpg

            String originalFilename = image.getOriginalFilename();
            if (originalFilename != null && originalFilename.lastIndexOf(".") != -1) {
                fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
            }

            // 如果没有提供proposerId，则使用当前用户ID
            if (proposerId == null) {
                proposerId = SecurityUtils.getLoginUser().getUser().getUserId().intValue();
            }

            String newFilename = dateStr + "_" + proposerId + "_" + String.format("%03d", count) + fileExtension;

            // 保存文件
            Path filePath = Paths.get(finalUploadDir + File.separator + newFilename);
            Files.write(filePath, image.getBytes());

            // 返回访问URL（使用相对路径）
            String imageUrl = "/profile/proposal/" + datePath.replace("\\", "/") + "/" + newFilename;

            // 创建返回数据对象
            ImageUploadResult result = new ImageUploadResult();
            result.setUrl(imageUrl);
            result.setName(newFilename);
            result.setSize(image.getSize());
            result.setContentType(contentType);

            return AjaxResult.success("上传成功", result);
        } catch (IOException e) {
            return AjaxResult.error("上传失败: " + e.getMessage());
        } catch (Exception e) {
            return AjaxResult.error("系统错误: " + e.getMessage());
        }
    }

    /**
     * 访问图片
     * @param year 年份
     * @param month 月份
     * @param day 日期
     * @param filename 文件名
     * @return 图片资源
     */
    @GetMapping("/image/{year}/{month}/{day}/{filename:.+}")
    @Anonymous
    public ResponseEntity<Resource> getImage(
            @PathVariable String year,
            @PathVariable String month,
            @PathVariable String day,
            @PathVariable String filename) {

        try {
            // 验证路径参数是否合法（只允许数字）
            if (!isValidPathParameter(year) || !isValidPathParameter(month) || !isValidPathParameter(day)) {
                return ResponseEntity.badRequest().build();
            }

            String fullPath = uploadDir + File.separator + year + File.separator + month + File.separator + day + File.separator + filename;
            File file = new File(fullPath);

            // 检查文件是否存在以及是否在上传目录内（防止路径遍历攻击）
            if (!file.exists() || !file.getCanonicalPath().startsWith(new File(uploadDir).getCanonicalPath())) {
                return ResponseEntity.notFound().build();
            }

            FileSystemResource resource = new FileSystemResource(file);
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_TYPE, Files.probeContentType(file.toPath()));
            headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(file.length()));

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);
        } catch (IOException e) {
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 验证路径参数是否合法（只允许数字）
     * @param param 路径参数
     * @return 是否合法
     */
    private boolean isValidPathParameter(String param) {
        if (param == null || param.isEmpty()) {
            return false;
        }
        Pattern pattern = Pattern.compile("^\\d+$");
        Matcher matcher = pattern.matcher(param);
        return matcher.matches();
    }

    /**
     * 图片上传结果类
     */
    public static class ImageUploadResult {
        private String url;
        private String name;
        private long size;
        private String contentType;

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public long getSize() {
            return size;
        }

        public void setSize(long size) {
            this.size = size;
        }

        public String getContentType() {
            return contentType;
        }

        public void setContentType(String contentType) {
            this.contentType = contentType;
        }
    }
}
